using System;
using System.Collections.Generic;
using FireStarterModeller.BO;
using FireStarterModeller.Logic;
using FireStarterModeller.Test.BO;
using Habanero.Base.Exceptions;
using Habanero.BO;
using NUnit.Framework;

namespace FireStarterModeller.Test.Logic
{
    [TestFixture]
    public class TestUIGridCreator_CreateGridDefFromDomainModel
    {

        #region Setup/Teardown

        [TestFixtureSetUp]
        public virtual void TestFixtureSetup()
        {
            TestUtilsLogic.SetupFixture();
        }

        [SetUp]
        public virtual void SetupTest()
        {
            TestUtilsLogic.SetupTest();
        }

        [TearDown]
        public virtual void TearDownTest(){}
        #endregion

        [Test]
        public void Test_CreateGridColumnDef_WhenPropNull_ShouldRaiseError()
        {
            //---------------Set up test pack-------------------
            UIGridCreator gridCreator = new UIGridCreator();
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            try
            {
                gridCreator.CreateColumn(new DMClass(), null);
                Assert.Fail("expected ArgumentNullException");
            }
                //---------------Test Result -----------------------
            catch (ArgumentNullException ex)
            {
                StringAssert.Contains("Value cannot be null", ex.Message);
                StringAssert.Contains("property", ex.ParamName);
            }
        }

        [Test]
        public void Test_CreateGridColumnDef_WhenClassSolutionNull_ShouldRaiseError()
        {
            //---------------Set up test pack-------------------
            DMProperty property = TestUtilsDMProperty.CreateUnsavedDefaultDMProperty();
            TestUtilsDMProperty.SetDMPropStringType(property);
            property.Class = TestUtilsDMClass.CreateUnsavedDefaultDMClass();
            UIGridCreator gridCreator = new UIGridCreator();
            //---------------Assert Precondition----------------
            Assert.IsNull(property.Class.Solution);
            //---------------Execute Test ----------------------
            try
            {
                gridCreator.CreateColumn(property.Class, property.PropertyName);
                Assert.Fail("expected ArgumentNullException");
            }
                //---------------Test Result -----------------------
            catch (HabaneroArgumentException ex)
            {
                StringAssert.Contains("You cannot create a column for a property that is not associated with a Solution", ex.Message);
            }
        }
        [Test]
        public void Test_CreateGridColumnDef_WhenPropTypeNull_ShouldRaiseError()
        {
            //---------------Set up test pack-------------------
            DMClass dmClass = TestUtilsDMClass.CreateUnsavedValidDMClass();
            DMProperty property = TestUtilsDMProperty.CreateUnsavedDefaultDMProperty();
            property.PropertyName = TestUtilsShared.GetRandomString();
            property.Class = dmClass;
            UIGridCreator gridCreator = new UIGridCreator();
            property.PropertyType = null;
            //---------------Assert Precondition----------------
            Assert.IsNull(property.PropertyType);
            //---------------Execute Test ----------------------
            try
            {
                gridCreator.CreateColumn(dmClass, property.PropertyName);
                Assert.Fail("expected ArgumentNullException");
            }
            //---------------Test Result -----------------------
            catch (HabaneroApplicationException ex)
            {
                StringAssert.Contains("The property Type for", ex.Message);
                StringAssert.Contains("cannot be null in method 'UIGridCreator.CreateColumn'", ex.Message);
            }
        }

        [Test]
        public void Test_CreateGridColumnDef_ShouldReferenceTheProperty()
        {
            //---------------Set up test pack-------------------
            SolutionCreator creator = new SolutionCreator();
            DMProperty property = TestUtilsDMProperty.CreateUnsavedDefaultDMPropertyWithClass(creator.CreateSolution());
            TestUtilsDMProperty.SetDMPropStringType(property);
            UIGridCreator gridCreator = new UIGridCreator();
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            UIGridColumnInfo gridColumn = gridCreator.CreateColumn(property.Class, property.PropertyName);
            //---------------Test Result -----------------------
            Assert.IsNotNull(gridColumn);
            Assert.AreSame(property, gridColumn.Property);
        }
        [Test]
        public void Test_CreateGridColumnDef_WhenString_ShouldHaveTextBoxPropertyAndColumnType()
        {
            //---------------Set up test pack-------------------
            SolutionCreator creator = new SolutionCreator();
            DMProperty property = TestUtilsDMProperty.CreateUnsavedDefaultDMPropertyWithClass(creator.CreateSolution());
            property.OrdinalPosition = 3;
            TestUtilsDMProperty.SetDMPropStringType(property);
            UIGridCreator gridCreator = new UIGridCreator();
            //---------------Assert Precondition----------------
            UICreatorTestUtils.AssertPropertyTypeIsString(property);
            Assert.IsNotNull(property.OrdinalPosition);
            Assert.Greater(property.OrdinalPosition, 0);
            //---------------Execute Test ----------------------
            UIGridColumnInfo gridColumn = gridCreator.CreateColumn(property.Class, property.PropertyName);
            //---------------Test Result -----------------------
            Assert.IsNotNull(gridColumn);
            Assert.IsNotNull(gridColumn.PropertyName);
            Assert.AreEqual(property.PropertyName, gridColumn.PropertyName);

            AssertGridColumnTypeIsTextBox(gridColumn);
            TestUtilsShared.AssertStringEmpty(gridColumn.Heading, "gridColumn.Label", "The Label should not be set since it is defaulted to the Property DisplayValue");
            Assert.IsTrue(gridColumn.Editable.GetValueOrDefault());
            Assert.IsFalse(gridColumn.Generated.GetValueOrDefault());
            Assert.AreEqual("left",gridColumn.Alignment);
            Assert.AreEqual(100, gridColumn.Width);
            Assert.AreEqual(property.OrdinalPosition, gridColumn.OrdinalPosition);
        }
        [Test]
        public void Test_CreateGridColumnDef_WhenInt_ShouldHaveTextBoxPropertyAndColumnType()
        {
            //---------------Set up test pack-------------------
            SolutionCreator creator = new SolutionCreator();
            DMProperty property = TestUtilsDMProperty.CreateUnsavedDefaultDMPropertyWithClass(creator.CreateSolution());
            TestUtilsDMProperty.SetDMPropIntType(property);
            UIGridCreator gridCreator = new UIGridCreator();
            //---------------Assert Precondition----------------
            UICreatorTestUtils.AssertPropertyTypeIsInt(property);
            //---------------Execute Test ----------------------
            UIGridColumnInfo gridColumn = gridCreator.CreateColumn(property.Class, property.PropertyName);
            //---------------Test Result -----------------------
            Assert.IsNotNull(gridColumn);
            Assert.IsNotNull(gridColumn.PropertyName);
            Assert.AreSame(property.PropertyName, gridColumn.PropertyName);

            AssertGridColumnTypeIsTextBox(gridColumn);
            TestUtilsShared.AssertStringEmpty(gridColumn.Heading, "gridColumn.Label", "The Label should not be set since it is defaulted to the Property DisplayValue");
            Assert.IsTrue(gridColumn.Editable.GetValueOrDefault());
            Assert.IsFalse(gridColumn.Generated.GetValueOrDefault());
            Assert.AreEqual("left",gridColumn.Alignment);
            Assert.AreEqual(100, gridColumn.Width);
        }

        [Test]
        public void Test_CreateTwoGridColumnDefs_String_ShouldBothHaveSameColumnType()
        {
            //---------------Set up test pack-------------------
            DMProperty property = TestUtilsDMProperty.CreateUnsavedDefaultDMPropertyWithClass();
            TestUtilsDMProperty.SetDMPropStringType(property);
            UIGridCreator gridCreator = new UIGridCreator();
            //---------------Assert Precondition----------------
            UICreatorTestUtils.AssertPropertyTypeIsString(property);
            //---------------Execute Test ----------------------
            UIGridColumnInfo gridColumn = gridCreator.CreateColumn(property.Class, property.PropertyName);
            UIGridColumnInfo gridColumn2 = gridCreator.CreateColumn(property.Class, property.PropertyName);
            //---------------Test Result -----------------------
            Assert.AreNotSame(gridColumn, gridColumn2);
            Assert.AreSame(gridColumn.UIGridColumnControlType, gridColumn2.UIGridColumnControlType);
        }

        [Test]
        public void Test_CreateTwoGridColumnDefs_Boolean_ShouldBothHaveSameColumnType()
        {
            //---------------Set up test pack-------------------
            SolutionCreator creator = new SolutionCreator();
            DMProperty property = TestUtilsDMProperty.CreateUnsavedDefaultDMPropertyWithClass(creator.CreateSolution());
            TestUtilsDMProperty.SetDMPropBooleanType(property);
            UIGridCreator gridCreator = new UIGridCreator();
            //---------------Assert Precondition----------------
            UICreatorTestUtils.AssertPropertyTypeIsBool(property);
            //---------------Execute Test ----------------------
            UIGridColumnInfo gridColumn = gridCreator.CreateColumn(property.Class, property.PropertyName);
            UIGridColumnInfo gridColumn2 = gridCreator.CreateColumn(property.Class, property.PropertyName);
            //---------------Test Result -----------------------
            Assert.AreNotSame(gridColumn, gridColumn2);
            Assert.AreSame(gridColumn.UIGridColumnControlType, gridColumn2.UIGridColumnControlType);
        }

        [Test]
        public void Test_CreateGridColumnDef_Bool_ShouldBeCheckBoxColumnType()
        {
            //---------------Set up test pack-------------------
            SolutionCreator creator = new SolutionCreator();
            DMProperty property = TestUtilsDMProperty.CreateUnsavedDefaultDMPropertyWithClass(creator.CreateSolution());
            TestUtilsDMProperty.SetDMPropBooleanType(property);
            UIGridCreator gridCreator = new UIGridCreator();
            //---------------Assert Precondition----------------
            UICreatorTestUtils.AssertPropertyTypeIsBool(property);
            //---------------Execute Test ----------------------
            UIGridColumnInfo gridColumn = gridCreator.CreateColumn(property.Class, property.PropertyName);
            //---------------Test Result -----------------------
            Assert.AreSame(property.PropertyName, gridColumn.PropertyName);
            AssertGridColumnTypeIsCheckBox(gridColumn);
        }

        [Test]
        public void Test_CreateGridColumnDef_Lookup_ShouldBeComboBoxColumnType()
        {
            //---------------Set up test pack-------------------
            SolutionCreator creator = new SolutionCreator();
            DMProperty property = TestUtilsDMProperty.CreateUnsavedDefaultDMPropertyWithClass(creator.CreateSolution());
            TestUtilsDMProperty.SetDMPropWithLookupList(property);
            UIGridCreator gridCreator = new UIGridCreator();
            //---------------Assert Precondition----------------
            UICreatorTestUtils.AssertPropertyTypeIsLookup(property);
            //---------------Execute Test ----------------------
            UIGridColumnInfo gridColumn = gridCreator.CreateColumn(property.Class, property.PropertyName);
            //---------------Test Result -----------------------
            AssertGridColumnTypeIsComboBox(gridColumn);
        }

        [Test]
        public void Test_CreateTwoGridColumnDefs_Lookup_ShouldBothHaveSameColumnType()
        {
            //---------------Set up test pack-------------------
            SolutionCreator creator = new SolutionCreator();
            DMProperty property = TestUtilsDMProperty.CreateUnsavedDefaultDMPropertyWithClass(creator.CreateSolution());
            TestUtilsDMProperty.SetDMPropWithLookupList(property);
            UIGridCreator gridCreator = new UIGridCreator();
            //---------------Assert Precondition----------------
            UICreatorTestUtils.AssertPropertyTypeIsLookup(property);
            //---------------Execute Test ----------------------
            UIGridColumnInfo gridColumn = gridCreator.CreateColumn(property.Class, property.PropertyName);
            UIGridColumnInfo gridColumn2 = gridCreator.CreateColumn(property.Class, property.PropertyName);
            //---------------Test Result -----------------------
            Assert.AreNotSame(gridColumn, gridColumn2);
            Assert.AreSame(gridColumn.UIGridColumnControlType, gridColumn2.UIGridColumnControlType);
        }

        [Test]
        public void Test_CreateGridInfo_OneProperty_ShouldHaveAppropriateColumnInfo()
        {
            //---------------Set up test pack-------------------
            DMClass dmClass = CreateClassWithOneLookupProperty();
            UIGridCreator gridCreator = new UIGridCreator();
            //---------------Assert Precondition----------------
            Assert.IsNotNull(dmClass);
            Assert.AreEqual(1, dmClass.Properties.Count);
            //---------------Execute Test ----------------------
            UIGridInfo gridInfo = gridCreator.CreateGrid(dmClass, dmClass.Properties);
            //---------------Test Result -----------------------
            Assert.IsNotNull(gridInfo);
            Assert.AreEqual(1, gridInfo.UIColumns.Count);
            AssertGridColumnTypeIsComboBox(gridInfo.UIColumns[0]);
            Assert.IsFalse(gridInfo.Generated.GetValueOrDefault());
        }
        [Test]
        public void Test_CreateGridInfo_TwoProperty_ShouldHaveAppropriateColumnInfo()
        {
            //---------------Set up test pack-------------------
            DMClass dmClass = CreateClassWithOneLookupProperty();
            DMProperty property1 = dmClass.Properties[0];
            property1.OrdinalPosition = 0;
            DMProperty dmProperty = dmClass.Properties.CreateBusinessObject();
            dmProperty.OrdinalPosition = 1;
            TestUtilsDMProperty.SetDMPropBooleanType(dmProperty);
            UIGridCreator gridCreator = new UIGridCreator();
            //---------------Assert Precondition----------------
            Assert.IsNotNull(dmClass);
            Assert.AreEqual(2, dmClass.Properties.Count);
            //---------------Execute Test ----------------------
            UIGridInfo gridInfo = gridCreator.CreateGrid(dmClass, dmClass.Properties);
            //---------------Test Result -----------------------
            Assert.IsNotNull(gridInfo);
            Assert.AreEqual(2, gridInfo.UIColumns.Count);
            gridInfo.UIColumns.Sort("OrdinalPosition", true, true);
            AssertGridColumnTypeIsComboBox(gridInfo.UIColumns[0]);
            AssertGridColumnTypeIsCheckBox(gridInfo.UIColumns[1]);
        }

        [Test]
        public void Test_CreateGridInfo_TwoProperty_OneObjectID_ShouldHaveObjectIDColumn()
        {
            //---------------Set up test pack-------------------
            DMClass dmClass = CreateClassWithOneLookupProperty();
            DMProperty dmProperty = dmClass.Properties.CreateBusinessObject();
            TestUtilsDMProperty.SetDMPropBooleanType(dmProperty);
            DMProperty dmProperty1 = dmClass.Properties.CreateBusinessObject();
            TestUtilsDMProperty.SetDMPropStringType(dmProperty1);
            dmClass.CreateObjectIdentity(dmProperty1);
            UIGridCreator gridCreator = new UIGridCreator();
            //---------------Assert Precondition----------------
            Assert.IsNotNull(dmClass);
            Assert.AreEqual(3, dmClass.Properties.Count);
            //---------------Execute Test ----------------------
            UIGridInfo gridInfo = gridCreator.CreateGrid(dmClass, dmClass.Properties);
            //---------------Test Result -----------------------
            Assert.IsNotNull(gridInfo);
            Assert.AreEqual(3, gridInfo.UIColumns.Count);
        }

        [Test]
        public void Test_CreateGridInfo_TwoProperty_OneKeepValuePrivate_ShouldHaveKeepvaluePrivateColumn()
        {
            //---------------Set up test pack-------------------
            DMClass dmClass = CreateClassWithOneLookupProperty();
            DMProperty dmProperty = dmClass.Properties.CreateBusinessObject();
            TestUtilsDMProperty.SetDMPropBooleanType(dmProperty);
            DMProperty property = dmClass.Properties.CreateBusinessObject();
            TestUtilsDMProperty.SetDMPropStringType(property);
            property.KeepValuePrivate = true;
            UIGridCreator gridCreator = new UIGridCreator();
            //---------------Assert Precondition----------------
            Assert.IsNotNull(dmClass);
            Assert.AreEqual(3, dmClass.Properties.Count);
            Assert.IsTrue(property.KeepValuePrivate.Value);
            //---------------Execute Test ----------------------
            UIGridInfo gridInfo = gridCreator.CreateGrid(dmClass, dmClass.Properties);
            //---------------Test Result -----------------------
            Assert.IsNotNull(gridInfo);
            Assert.AreEqual(3, gridInfo.UIColumns.Count);
        }

        [Test]
        public void Test_CreateGridInfo_TwoProperty_OneKeepValuePrivateNull_ShouldCreateAllColumns()
        {
            //---------------Set up test pack-------------------
            DMClass dmClass = CreateClassWithOneLookupProperty();
            DMProperty dmProperty = TestUtilsDMProperty.CreateUnsavedValidDMProperty(dmClass);
            TestUtilsDMProperty.SetDMPropBooleanType(dmProperty);
            DMProperty property = TestUtilsDMProperty.CreateUnsavedValidDMProperty(dmClass);
            property.KeepValuePrivate = null;
            UIGridCreator gridCreator = new UIGridCreator();
            //---------------Assert Precondition----------------
            Assert.IsNotNull(dmClass);
            Assert.AreEqual(3, dmClass.Properties.Count);
            Assert.IsNull(property.KeepValuePrivate);
            //---------------Execute Test ----------------------
            UIGridInfo gridInfo = gridCreator.CreateGrid(dmClass, dmClass.Properties);
            //---------------Test Result -----------------------
            Assert.IsNotNull(gridInfo);
            Assert.AreEqual(3, gridInfo.UIColumns.Count);
        }
        [Test]
        public void Test_CreateUIGridFilter_WhenPropertiesNull_ShouldRaiseError()
        {
            //---------------Set up test pack-------------------
            UIGridCreator gridCreator = new UIGridCreator();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            try
            {
                gridCreator.CreateGrid(new DMClass(), (List<string>)null);
                Assert.Fail("expected ArgumentNullException");
            }
            //---------------Test Result -----------------------
            catch (ArgumentNullException ex)
            {
                StringAssert.Contains("Value cannot be null", ex.Message);
                StringAssert.Contains("properties", ex.ParamName);
            }

        }
        [Test]
        public void Test_CreateUIGridFilter_WhenDMClassNull_ShouldRaiseError()
        {
            //---------------Set up test pack-------------------
            UIGridCreator gridCreator = new UIGridCreator();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            try
            {
                gridCreator.CreateGrid(null, new List<string>());
                Assert.Fail("expected ArgumentNullException");
            }
            //---------------Test Result -----------------------
            catch (ArgumentNullException ex)
            {
                StringAssert.Contains("Value cannot be null", ex.Message);
                StringAssert.Contains("dmClass", ex.ParamName);
            }

        }

        [Test]
        public void Test_CreateGridInfo_TwoProperty_ShouldHaveCorrectOrder()
        {
            //---------------Set up test pack-------------------
            DMClass dmClass = CreateClassWithOneLookupProperty();
            DMProperty dmProperty1 = dmClass.Properties[0];
            dmProperty1.DisplayName = TestUtilsShared.GetRandomString();
            DMProperty dmProperty2 = dmClass.Properties.CreateBusinessObject();
            dmProperty2.DisplayName = TestUtilsShared.GetRandomString();
            TestUtilsDMProperty.SetDMPropBooleanType(dmProperty2);
            UIGridCreator gridCreator = new UIGridCreator();
            BusinessObjectCollection<DMProperty> selectedProps = new BusinessObjectCollection<DMProperty>();
            selectedProps.Add(dmProperty2);
            selectedProps.Add(dmProperty1);
            //---------------Assert Precondition----------------
            Assert.IsNotNull(dmClass);
            Assert.AreEqual(2, dmClass.Properties.Count);
            Assert.AreEqual(1, dmProperty1.OrdinalPosition);
            Assert.AreEqual(2, dmProperty2.OrdinalPosition);
            //---------------Execute Test ----------------------
            UIGridInfo gridInfo = gridCreator.CreateGrid(dmClass, selectedProps);
            UIView uiView =  dmClass.UIViews.CreateBusinessObject();
            gridInfo.UIView = uiView;
            uiView.Save();
            //---------------Test Result -----------------------
            Assert.IsNotNull(gridInfo);
            Assert.AreEqual(2, gridInfo.UIColumns.Count);
            gridInfo.UIColumns.Sort("OrdinalPosition", true, true);
            UIGridColumnInfo column1 = gridInfo.UIColumns[0];
            Assert.AreSame(dmProperty1.PropertyName, column1.PropertyName);
            Assert.AreEqual(dmProperty1.OrdinalPosition, column1.OrdinalPosition);
            UIGridColumnInfo column2 = gridInfo.UIColumns[1];
            Assert.AreSame(dmProperty2.PropertyName, column2.PropertyName);
            Assert.AreEqual(dmProperty2.OrdinalPosition, column2.OrdinalPosition);
        }

        private static DMClass CreateClassWithOneLookupProperty()
        {
            SolutionCreator creator = new SolutionCreator();
            DMProperty property = TestUtilsDMProperty.CreateUnsavedDefaultDMPropertyWithClass(creator.CreateSolution());
            TestUtilsDMProperty.SetDMPropWithLookupList(property);
            return (DMClass) property.Class;
        }

        private static void AssertGridColumnTypeIsComboBox(UIGridColumnInfo gridColumn)
        {
            Assert.IsNotNull
                (gridColumn.UIGridColumnControlType, "The UIGridColumn Type should be TextBox and Cannot be null");
            Assert.AreEqual("System.Windows.Forms", gridColumn.UIGridColumnControlType.AssemblyName);
            Assert.AreEqual("DataGridViewComboBoxColumn", gridColumn.UIGridColumnControlType.TypeName);
        }

        private static void AssertGridColumnTypeIsCheckBox(UIGridColumnInfo gridColumn)
        {
            Assert.IsNotNull
                (gridColumn.UIGridColumnControlType, "The UIGridColumn Type should be TextBox and Cannot be null");
            Assert.AreEqual("System.Windows.Forms", gridColumn.UIGridColumnControlType.AssemblyName);
            Assert.AreEqual("DataGridViewCheckBoxColumn", gridColumn.UIGridColumnControlType.TypeName);
        }

        private static void AssertGridColumnTypeIsTextBox(UIGridColumnInfo gridColumn)
        {
            Assert.IsNotNull
                (gridColumn.UIGridColumnControlType, "The UIGridColumn Type should be TextBox and Cannot be null");
            Assert.AreEqual("System.Windows.Forms", gridColumn.UIGridColumnControlType.AssemblyName);
            Assert.AreEqual("DataGridViewTextBoxColumn", gridColumn.UIGridColumnControlType.TypeName);
        }

    }

}